package com.bonc.rms.utils.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.range.RangeBuilder;
import org.elasticsearch.search.aggregations.bucket.terms.TermsBuilder;
import org.elasticsearch.search.aggregations.metrics.MetricsAggregationBuilder;

import com.bonc.odk.es.platform.pagination.PagedList;
import com.bonc.odk.es.search.IAggregationBuilder;
import com.bonc.odk.es.search.ISearchBuilder;
import com.bonc.odk.es.search.ISearchBuilder.Operator;
import com.bonc.odk.es.search.impl.AggregationBuilderImpl;
import com.bonc.odk.es.search.impl.SearchBuilderImpl;
import com.bonc.odk.es.search.impl.SearchCondition.Conjunction;
import com.bonc.odk.exceptions.SearchException;
import com.bonc.odk.logmanager.LogManager;
import com.bonc.rms.config.Config;
import com.bonc.rms.utils.ESManager;
import com.bonc.rms.utils.IESSearchUtil;


public class ESSearchUtilImpl implements IESSearchUtil {

	public List<Map<String, Object>> getPageListByKeyword(String property, String keyword, int pageSize,
			int pageIndex) {
		List<Map<String, Object>> pageList = new ArrayList<>();
		ISearchBuilder searchBuilder = new SearchBuilderImpl();
		searchBuilder.filterField(property, keyword, ISearchBuilder.Operator.Match).page(pageIndex, pageSize)
		.setMinScore(0);
		try {
			PagedList res = ESManager.getInstance().getSearchService().pageList(Config.ELASTICSEARCH_INDEX,
					Config.ELASTICSEARCH_TYPE, searchBuilder);
			pageList = res.getRows();
			Map<String, Object> pageData = new HashMap<>();
			pageData.put("totalCount", res.getTotalItemCount());
			pageData.put("totalPage", res.getPageTotal());
			pageList.add(pageData);
		} catch (SearchException e) {
			e.printStackTrace();
		}
		return pageList;
	}

	@Override
	public Map<String, Object> getPageListById(String id) {
		Map<String, Object> res = new HashMap<>();
		try {
			res = ESManager.getInstance().getSearchService().get(Config.ELASTICSEARCH_INDEX,
					Config.ELASTICSEARCH_TYPE, id);
		} catch (SearchException e) {
			e.printStackTrace();
		}
		return res;
	}
	
	@Override
	public List<Map<String, Object>> getPageListByMap(Map<String, Object> map, int pageSize,
			int pageIndex) {
		String[] keys = new String[map.size()];
		map.keySet().toArray(keys);
		ISearchBuilder searchBuilder = new SearchBuilderImpl();
		if(map.get("workingExperience") == null){
			searchBuilder.filterField(keys[0], (String)map.get(keys[0]), Operator.Match).page(pageIndex, pageSize);
			for(int i=1; i<map.size(); i++){
				searchBuilder.filterFieldByChild(keys[i], (String)map.get(keys[i]), Operator.Match, Conjunction.AND);
			}
		}else{
			String exp = (String) map.get("workingExperience");
//			System.out.println(exp.substring(0, 1)+exp.substring(2, exp.length()));
			searchBuilder.filterField("workingExperience", exp.substring(0, 1), Operator.GreaterThanOrEqual);
			searchBuilder.filterFieldByChild("workingExperience", exp.substring(2, exp.length()), 
					Operator.LessThan, Conjunction.AND);
			for(int i=0; i<map.size(); i++){
				if("workingExperience" != keys[i]){
					searchBuilder.filterFieldByChild(keys[i], (String)map.get(keys[i]), Operator.Match, Conjunction.AND);
				}
			}
		}
		List<Map<String, Object>> pageList = new ArrayList<>();
		PagedList res;		
		try {
			res = ESManager.getInstance().getSearchService().pageList(Config.ELASTICSEARCH_INDEX,
					Config.ELASTICSEARCH_TYPE, searchBuilder);
			pageList = res.getRows();
			Map<String, Object> pageData = new HashMap<>();
			pageData.put("totalCount", res.getTotalItemCount());
			pageData.put("totalPage", res.getPageTotal());
			pageList.add(pageData);
		} catch (SearchException e) {
			e.printStackTrace();
		}
		return pageList;
	}

	
	
	@SuppressWarnings("rawtypes")
	@Override
	public double countAgg(String field) {
		IAggregationBuilder aggregationBuilder = new AggregationBuilderImpl();
		MetricsAggregationBuilder aggregation = aggregationBuilder.aggCount("count", field);
		double result = ESManager.getInstance().getSearchService()
				.metricsAggregation(Config.ELASTICSEARCH_INDEX, 
				Config.ELASTICSEARCH_TYPE, aggregation);
		return result;
	}

	@SuppressWarnings("rawtypes")
	@Override
	public long filterAgg(String field, String value) {
		IAggregationBuilder aggregationBuilder = new AggregationBuilderImpl();
		AggregationBuilder aggregation = aggregationBuilder.aggFilter("filter", field, value);
		long result = ESManager.getInstance().getSearchService()
				.aggregation(Config.ELASTICSEARCH_INDEX, Config.ELASTICSEARCH_TYPE, aggregation);
		return result;
	}

	@SuppressWarnings("rawtypes")
	@Override
	public List<Map<String, Double>> termAgg(String field) {
		IAggregationBuilder aggregationBuilder = new AggregationBuilderImpl();
		AggregationBuilder aggregation = aggregationBuilder.aggTerms("terms", field);
		List<Map<String, Double>> result = ESManager.getInstance().getSearchService()
				.termsAggregation(Config.ELASTICSEARCH_INDEX, Config.ELASTICSEARCH_TYPE
						, (TermsBuilder) aggregation);
		
		return result;
	}

	@Override
	public Map<String, Long> rangeAgg(String field, float to, float from) {
		IAggregationBuilder aggregationBuilder = new AggregationBuilderImpl();
		AggregationBuilder aggregation = aggregationBuilder.aggRange("range", field, to, from);
		Map<String, Long> result = new HashMap<>();
		result = ESManager.getInstance().getSearchService()
				.rangeAggregation(Config.ELASTICSEARCH_INDEX, Config.ELASTICSEARCH_TYPE,
						(RangeBuilder) aggregation);
		
		return result;
	}

	@Override
	public List<Map<String, Object>> getPageListByList(List<String> list, int pageSize, int pageIndex) {
		ISearchBuilder searchBuilder = new SearchBuilderImpl();
		if(list.get(0) != null){
			searchBuilder.filterField("_all", list.get(0), ISearchBuilder.Operator.Match).page(pageIndex, pageSize)
			.setMinScore(0);
		}
		for(int i = 1; i < list.size(); i++){
			searchBuilder.filterFieldByChild("_all", list.get(i), Operator.Match, Conjunction.AND);
		}
		List<Map<String, Object>> pageList = new ArrayList<>();

		try {
			PagedList res = ESManager.getInstance().getSearchService().pageList(Config.ELASTICSEARCH_INDEX,
					Config.ELASTICSEARCH_TYPE, searchBuilder);
			pageList = res.getRows();
			Map<String, Object> pageData = new HashMap<>();
			pageData.put("totalCount", res.getTotalItemCount());
			pageData.put("totalPage", res.getPageTotal());
			pageList.add(pageData);
		} catch (SearchException e) {
			e.printStackTrace();
		}
		return pageList;
	}


	
}
